﻿using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Tapper
{
    class Mugs : Character
    {
        private float m_beer;
        private Client m_client;
        private Color m_colorMug;
        private bool m_beerIsFull;
        private Vector2 m_moveDir;        
        internal MugState m_mugState;
        readonly Texture2D m_texture;
        private float m_distanceDebug;
        internal TableState m_tableState;
        private readonly Player m_player;
        private readonly float m_posXStart; // inicial position of the mug
        private float m_beerDistanceClient;
        private float m_beerDistance;
        private float m_clientStay;

        public Mugs(World world, Texture2D tex, Vector2 pos, Vector2 vel, Player player, Client client, MugState mugState, TableState tableState) : base(world, tex, pos, vel)
        {
            m_posXStart  = m_pos.X;
            m_pos.X      = pos.X; // Posição do Player mais 10.0f
            m_accel      = 250.0f;
            m_maxvel     = 150.0f;
            m_scale      = 0.5f;
            m_texture    = tex;
            m_colorMug   = Color.Red;
            m_player     = player;
            m_client     = client;
            m_mugState   = mugState;
            m_tableState = tableState;
            m_moveDir    = new Vector2(0.0f, 0.0f);
        }

        private void Returning()
        {
            //move X para direita
            m_maxvel    = 150.0f;
            m_moveDir.X = -1.0f;
            //procura colisão com player (foreach all entities)
            foreach (var table in m_world.m_entities.Select(current => current as Table))
            {
                if (table != null)
                {
                    foreach (var player in m_world.m_entities.Select(currentEntity => currentEntity as Player))
                    {
                        if (m_tableState == table.m_tableState)
                        {
                            m_distanceDebug = Math.Abs(table.m_pos.X - m_pos.X); //Vector2.Distance(table.m_pos, m_pos);

                            //  se chegou ao final da mesa
                            if (m_distanceDebug < 10f)
                            {
                                //client.m_amountOfFood += 1.0f;
                                m_world.DelEntity(this);
                            }

                            if (player != null)
                            {
                                var distance = Vector2.Distance(player.m_pos, m_pos);
                                //  se acertou o player, destroi o copo
                                if (distance < 16f)
                                {
                                    //client.m_amountOfFood += 1.0f;
                                    m_world.DelEntity(this);
                                }
                            }                            
                        }
                    }
                }
                //var player = current as Player;
                //if (player != null)
                //{
                //    var distance = Vector2.Distance(player.m_pos, m_pos);
                //    //  se acertou o player, destroi o copo
                //    if (distance < 1f)
                //    {
                //        //client.m_amountOfFood += 1.0f;
                //        m_world.DelEntity(this);
                //    }
                //}
            }
            //se X saiu da mesa, GAME OVER (e quebra o copo, m_State = MugState.Breaking) 
        }

        private void OnClient(float deltaTime)
        {
            m_pos = m_client.m_pos;
            //copiar a posição do client para si
            m_client.m_moveDir.X = 1.0f;

            //aumenta o tempo 
            m_beerDistance += deltaTime * 1f; //* m_drinkRate;

            //tempo que o cliente volta para traz
            if (m_beerDistance >= m_beerDistanceClient)
            {
                m_clientStay        += deltaTime * 1f; //* m_drinkRate;
                m_client.m_moveDir.X = 0.0f;

                if (m_clientStay >= 2)
                {
                    m_clientStay         = 0.0f;
                    m_beer               = 0.0f;
                    m_client.m_moveDir.X = 0.0f;
                    m_mugState           = MugState.Returning;
                    m_client.m_mugs      = null;
                    //(usar metodo no client para setar o copo?)
                }                                
            }
        }

        private void Serving()
        {
            foreach (var entity in m_world.m_entities)
            {
                var mug = entity as Mugs;

                if (mug != null)
                {
                    var distance = Vector2.Distance(m_player.m_pos, mug.m_pos);
                    if (distance < 16.0f)
                    {
                        m_moveDir.X    = 1.0f;
                        mug.m_colorMug = Color.GreenYellow;
                    }
                }
            }

            foreach (var entity in m_world.m_entities)
            {
                var client = entity as Client;
                if (client != null)
                {
                    /*var rand = new Random();*/
                    var distance = Vector2.Distance(m_pos, client.m_pos);

                    if (distance < 16.0f && m_beerIsFull)
                    {
                        // Se cliente não estiver bebendo
                        if (client.m_mugs == null)
                        {
                            //client.m_moveDir.X = 1.0f;                                    
                            m_maxvel             = 0.0f;
                            m_client             = client;
                            m_client.m_mugs      = this;
                            m_beerDistanceClient = client.m_distanceOnMug;
                            m_mugState           = MugState.OnClient;
                        }
                    }
                    //se X saiu da mesa, GAME OVER (e quebra o copo, m_State = MugState.Breaking) 
                }
            }
        }
        
        private void OnPlayer(float deltaTime)
        {            
            // perguntar ao player se está utilizando o tap (m_Player.m_UsingTap)
            if (m_player.m_usingTap)
            {                
                m_tableState = m_player.m_tableState;
                // aumenta a quantidade de cerveja (m_Beer += delta_time * 1.0f)
                
                m_beer    += deltaTime * 3f; //0.5f
                m_colorMug = Color.Violet;

                if (m_beer >= 1.0f)
                {                    
                    m_beerIsFull = true;
                    m_colorMug   = Color.Blue;                    
                }
            }
            else
            {
                // está cheio?
                if (m_beerIsFull)
                {
                    m_colorMug = Color.Azure;
                    m_mugState = MugState.Serving;
                }
                // destroi o copo
                else
                    m_world.DelEntity(this);
            }
            if (m_player.m_isMoving)
            {
                m_beer = 0.0f;
                m_player.m_isMoving = !m_player.m_isMoving;
                m_mugState = MugState.OnPlayer;
            }
        }

        protected override Vector2 GetPosX()
        {
            return m_moveDir;
        }

        public override void Update(GameTime gameTime)
        {
            foreach (var current in m_world.m_entities)
            {
                var mug = current as Mugs;
                if (mug != null)
                    if (!mug.m_pos.Y.Equals(m_player.m_pos.Y) && mug.m_pos.X.Equals(m_posXStart))
                        m_world.DelEntity(mug);
            }
            var deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
            switch (m_mugState)
            {                
                case MugState.OnPlayer:
                    OnPlayer(deltaTime);
                    break;
                case MugState.Serving:
                    Serving();
                    break;
                case MugState.OnClient:
                    OnClient(deltaTime);
                    break;                
                case MugState.Returning:
                    Returning();
                    break;
                case MugState.Breaking:                    
                    break;                
            }
            base.Update(gameTime);
        }        

        public override void Draw(GameTime gametime, SpriteBatch spritebatch)
        {
            //! Colocar Mug na frente das outras layers
            var vPlayerScale = new Vector2(m_scale, m_scale);
            var vPlayerSize  = new Vector2(m_texture.Width, m_texture.Height);

            const string gameOverText = "Distance MUG TABLE:";
            var fontGameOrigin = m_world.m_font.MeasureString(gameOverText) / 2;            
            spritebatch.DrawString(m_world.m_font, gameOverText + m_distanceDebug, new Vector2(150f,150f), Color.LightGreen, 0, fontGameOrigin, 1.0f, SpriteEffects.None, 0.5f);
            spritebatch.Draw(m_texture, m_pos, null, m_colorMug, 0.0f, vPlayerSize * 0.5f, vPlayerScale, SpriteEffects.None, 0f);
        }
    }
}